require 'net/http'
require 'uri'

class Torrent < ActiveRecord::Base
	validates_presence_of :name
	has_and_belongs_to_many :users
	#validates_uniqueness_of :name, :scope => :user_id , :message => 'already uploaded!'
	validates_format_of :name, :with => /(\w)*.[^(torrent)]/i, :message => 'not a torrent file!'
	
	def store(upload, user_id)
		name = sanitize_filename upload.original_filename
		directory = "/var/rails/torrent_dam/public/data/" + user_id + "/"
		path = File.join(directory, name)
		f = File.open(path, "wb")
		filename = File.expand_path(path)
		f.write(upload.read)
		f.close
		uri = URI.parse 'http://localhost:9091/transmission/rpc'
		Net::HTTP.new(uri.host, uri.port).start { |http|
			response = http.post '/transmission/rpc', {'method' => 'torrent-add', 'arguments' => {'filename' => filename}}.to_json
			if response.code == '401'
				logger.debug "********************** UNAUTHORIZED **********************************"
				return {:transmission_id => -1}
			end
			if response.code == '409'
					logger.debug "**************************************** 409 ***********************************"
					response = http.post '/transmission/rpc', {'method' => 'torrent-add', 'arguments' => {'filename' => filename}}.to_json, response
			end
			if response.code == '200'
				logger.debug "**************************************** 200 OK ***********************************"
				json_resp = JSON.parse response.body
				if json_resp['result'] == 'duplicate torrent'
					logger.debug "********************************* DUP TOR ***********************************"
					response = http.post '/transmission/rpc', {'method' => 'torrent-get', 'arguments' => {'fields' => ['id', 'hashString']}}.to_json, response
					if response.code == '409'
						logger.debug "SECOND 409"
						response = http.post '/transmission/rpc', {'method' => 'torrent-get', 'arguments' => {'fields' => ['id', 'hashString']}}.to_json, response
						if response.code == '200'
							json_resp = JSON.parse response.body
							torrent_list = json_resp['arguments']['torrents']
							logger.debug json_resp
							hash_line = IO.popen('transmissioncli -i ' + filename).readlines[1]
							hash = hash_line.split[1]			
							torrent_list.each do |tor|
									if hash == tor['hashString']
										return {:transmission_id => tor['id'], :t_hash => tor['hashString'], :dup_tor => "true"}
									end
							end
							# we shouldn't get here
							return {:transmission_id => -1}
						end
					end
					#return {:transmission_id => 'duplicate torrent', :torrent_list => torrent_list}
					#elsif response.code == '409'
					#	logger.debug "******************************* UNKNOWN ERROR *****************************"
					#	return {:transmission_id => -1}
					#end
				end
				if json_resp['arguments']['torrent-added'].nil?
					return {:transmission_id => -1}
				end
				{:transmission_id => json_resp['arguments']['torrent-added']['id'], :t_hash => json_resp['arguments']['torrent-added']['hashString'], :dup_tor => "false"}
			end
		}
	end

	def sanitize_filename(filename)
		returning filename.strip do |name|
			# NOTE: File.basename doesn't work right with Windows paths on Unix
			# get only the filename, not the whole path
			name.gsub! /^.*(\\|\/)/, ''
			# Finally, replace all non alphanumeric, underscore
			# or periods with underscore
			name.gsub! /[^\w\.\-]/, '_'
		end
	end
	
	def del_torrent
		uri = URI.parse 'http://localhost:9091/transmission/rpc'
		Net::HTTP.new(uri.host, uri.port).start { |http|
			response = http.post '/transmission/rpc', {'method' => 'torrent-remove', 'arguments' =>  {'ids' => [self.transmission_id], 'delete-local-data' => true }}.to_json
			if response.code == '401'
				return -1
			end
			if response.code == '409'
					response = http.post '/transmission/rpc', {'method' => 'torrent-remove', 'arguments' => {'ids' => [self.transmission_id], 'delete-local-data' => true }}.to_json, response		
			end
			if response.code == '200'
				if !self.t_hash.nil?
					File.delete("/var/rails/torrent_dam/public/data/completed/" + self.t_hash + ".zip") if File.exist?("/var/rails/torrent_dam/public/data/completed/" + self.t_hash + ".zip")
				end
			end
		}
	end
	
	def start_download(user_id, torrent)
		filename = '/var/rails/torrent_dam/public/data/' + user_id.to_s + '/' + sanitize_filename(torrent)
		uri = URI.parse 'http://localhost:9091/transmission/rpc'
		Net::HTTP.new(uri.host, uri.port).start { |http|
			response = http.post '/transmission/rpc', {'method' => 'torrent-add', 'arguments' => {'filename' => filename}}.to_json
			if response.code == '401'
				return -1
			end
			if response.code == '409'
					response = http.post '/transmission/rpc', {'method' => 'torrent-add', 'arguments' => {'filename' => filename}}.to_json, response		
			end
			if response.code == '200'
				json_resp = JSON.parse response.body
				if json_resp['arguments']['torrent-added'].nil?
					return -1
				end
				transmission_id = json_resp['arguments']['torrent-added']['id']
			end
		}
	end

	def check_status
		if File.exist?("/var/rails/torrent_dam/public/data/completed/" + self.t_hash.to_s + ".zip")
			return 100
		else
			uri = URI.parse 'http://localhost:9091/transmission/rpc'
			Net::HTTP.new(uri.host, uri.port).start { |http|
				response = http.post '/transmission/rpc', {'method' => 'torrent-get', 'arguments' => {'ids' => [self.transmission_id], 'fields' => ['percentDone']}}.to_json
				if response.code == '401'
					return -1
				end
				if response.code == '409'
						response = http.post '/transmission/rpc', {'method' => 'torrent-get', 'arguments' => {'ids' => [self.transmission_id], 'fields' => ['percentDone']}}.to_json, response		
						#response = http.post '/transmission/rpc', {'method' => 'torrent-get', 'arguments' => {'fields' => ['id','percentDone']}}.to_json, response		
				end
				if response.code == '200'
					@res = JSON.parse response.body
				else 
					return -1
				end
			}
			logger.debug @res
			if !@res['arguments']['torrents'][0].nil?
				status = @res['arguments']['torrents'][0]['percentDone']
			else
				status = 0
			end
			logger.debug status
			if (status == 1.0 && !File.exist?("/var/rails/torrent_dam/public/data/completed/" + self.t_hash.to_s + ".zip"))
				logger.debug "OKAY"
				p = fork {
							logger.debug "t_hash: " + self.t_hash
							logger.debug "name: " + self.name
							exec("cd /var/rails/torrent_dam/public/data/downloading; zip -r /var/rails/torrent_dam/public/data/completed/" + self.t_hash.to_s + ".zip ./" + self.name)
						}
				Process.detach p
			end
			return status * 95
		end
		-1
	end

end
